package cn.honqun.tinycms.service.impl;

import cn.honqun.tinycms.FileObjectNotFoundException;
import cn.honqun.tinycms.common.exce.ApplicationException;
import cn.honqun.tinycms.domain.entity.FileObject;
import cn.honqun.tinycms.service.AbstractFileObjectService;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.model.OSSObject;
import com.aliyuncs.exceptions.ClientException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

@Slf4j
public class FileObjectServiceOSS extends AbstractFileObjectService {
    private OSSClient ossClient;

    @PostConstruct
    public void startup() throws ClientException {
        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量
        // OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider =
                CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        ossClient = (OSSClient) new OSSClientBuilder()
                .build(fileObjectProperties.getEndpoint(), credentialsProvider);
        log.info("启动OSS");
    }

    @PreDestroy
    public void shutdown() {
        log.info("关闭OSS");
        ossClient.shutdown();
    }

    @Override
    public FileObject create(MultipartFile file) {
        String bucketName = fileObjectProperties.getBucketName();
        String objectName = fileObjectProperties.getLocal() + file.getOriginalFilename();
        log.debug("Object Name {}", objectName);

        try {
            ossClient.putObject(bucketName, objectName, file.getInputStream());
        } catch (IOException e) {
            throw new ApplicationException(e);
        }

        FileObject fileObject = new FileObject();
        fileObject.setUri(StrUtil.SLASH + objectName);
        fileObject.setUrl(fileObjectProperties.getHost() + fileObject.getUri());
        fileObject.setSize(file.getSize());
        fileObject.setSizeText(FileUtil.readableFileSize(file.getSize()));
        fileObject.setOriginalName(file.getOriginalFilename());
        fileObjectMapper.insert(fileObject);

        return fileObject;
    }

    @Override
    public void remove(String url) {
        FileObject fileObject = selectByKey(url);
        if (fileObject == null) {
            throw new FileObjectNotFoundException();
        }
        //删除数据
        fileObjectMapper.delete(fileObject);

        String key = getKey(fileObject);
        //删除文件对象
        String bucketName = fileObjectProperties.getBucketName();
        ossClient.deleteObject(bucketName, key);
    }

    @Override
    public void read(String url, OutputStream out) {
        FileObject fileObject = selectByKey(url);
        if (fileObject == null) {
            throw new FileObjectNotFoundException();
        }
        String key = getKey(fileObject);
        String bucketName = fileObjectProperties.getBucketName();
        OSSObject ossObject = ossClient.getObject(bucketName, key);

        try (InputStream in = ossObject.getObjectContent()) {
            FileCopyUtils.copy(in, out);
        } catch (IOException e) {
            e.printStackTrace();
            throw new ApplicationException(e);
        }
    }

    private String getKey(FileObject fileObject) {
        //OSS的Key是没有/开头的
        String key = fileObject.getUri();
        if (StrUtil.startWith(key, StrUtil.SLASH)) {
            key = key.substring(1);
        }
        return key;
    }
}
